package model;
import java.io.Serializable;
import java.net.UnknownHostException;
import java.util.ArrayList;

import org.codehaus.jackson.annotate.JsonIgnoreProperties;
import org.workplicity.entry.Entry;
import org.workplicity.util.Helper;
import org.workplicity.util.MongoHelper;
import org.workplicity.worklet.WorkletContext;

import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
import com.mongodb.util.JSON;

import cc.test.bridge.BridgeConstants.State;
import cc.test.bridge.BridgeInterface;
import cc.test.bridge.LineInterface;
import cc.test.bridge.SublineInterface;
import cc.test.bridge.TransactionInterface;


@JsonIgnoreProperties(ignoreUnknown = true)
public class Line extends Entry implements LineInterface, SublineInterface
{
	protected Boolean isSubline;
	protected Integer parentLineId;
	protected String repositoryName;
	protected Integer budgetId;
	protected String name;
	protected Integer number;
	protected ArrayList<Integer> sublineIds;
	protected ArrayList<Integer> transactionIds;
	private static final long serialVersionUID = 1L;
	
	public Line()
	{
		this.isSubline = false;
		this.parentLineId = -1;
		this.repositoryName = "Lines";
		this.budgetId = -1;
		this.name = "N/A";
		this.number = -1;
		this.sublineIds = new ArrayList<Integer>();
		this.transactionIds = new ArrayList<Integer>();
	}
	
	public Line(Integer budgetId)
	{
        this.budgetId = budgetId;
        this.isSubline = false;
		this.parentLineId = -1;
		this.repositoryName = "Lines";
		this.name = "N/A";
		this.number = -1;
		this.sublineIds = new ArrayList<Integer>();
		this.transactionIds = new ArrayList<Integer>();
    }
	
	public Line(Boolean isSubline, Integer parentLineId)
	{
		this.isSubline = true;
		this.parentLineId = parentLineId;
		this.repositoryName = "Lines";
		this.budgetId = -1;
		this.name = "N/A";
		this.number = -1;
		this.sublineIds = new ArrayList<Integer>();
		this.transactionIds = new ArrayList<Integer>();
	}
	
	public Integer getBudgetId()
	{
		return this.budgetId;
	}
	
	public void setBudgetId(Integer arg0)
	{
		this.budgetId = arg0;
		BridgeHelper.getHamper().put(this, State.UPDATE);
	}
	
	public ArrayList<Integer> getSublineIds()
	{
		return this.sublineIds;
	}
	
	public void setSublineIds(ArrayList<Integer> arg0)
	{
		this.sublineIds = arg0;
		BridgeHelper.getHamper().put(this, State.UPDATE);
	}

	@Override
	public Boolean commit()
	{
		Boolean successful = true;
		State state = BridgeHelper.getHamper().get(this);
		 
        if (state != null) {
        	if (state == State.CREATE || state == State.UPDATE){

                try
				{
                	if(state == State.UPDATE){
                		MongoHelper.update(this, "cc", this.getRepositoryName());
                	}
                	else{
                		MongoHelper.insert(this, "cc", this.getRepositoryName());
                	}
				} catch (Exception e)
				{
					System.out.println("----------------------------------------------------");
					e.printStackTrace();
				}
        		if(this.isSubline && state == State.CREATE){
        			for(BridgeInterface bridge : BridgeHelper.getHamper().keySet()) {
        				if(bridge instanceof Line){
        					if(((Line) bridge).getId() == this.parentLineId){
        						((Line) bridge).sublineIds.add(this.id);
        					}
        				}
        			}
        		}
        	}
            
            else if (state == State.DELETE){
            	Mongo mongo = null;
          		try
          		{
          			mongo = new Mongo();
          		} catch (UnknownHostException e)
          		{
          			// TODO Auto-generated catch block
          			e.printStackTrace();
          		} catch (MongoException e)
          		{
          			// TODO Auto-generated catch block
          			e.printStackTrace();
          		}
          		
                  DB db = mongo.getDB("cc");
                  DBCollection collection = db.getCollection("Lines");
                  collection.remove(new BasicDBObject("entry.id", this.getId()));
        		for(BridgeInterface bridge : BridgeHelper.getHamper().keySet()) {
    				if(bridge.getId() == this.parentLineId){
    					((Line) bridge).sublineIds.remove(this.id);
    				}
    			}
            }
        }
        

        return successful;
	}

	@Override
	public String getName()
	{
		return this.name;
	}

	@Override
	public void setName(String arg0)
	{
		this.name = arg0;
		BridgeHelper.getHamper().put(this, State.UPDATE);
	}

	@Override
	public void add(SublineInterface subline)
	{
		BridgeHelper.getHamper().put(subline, State.CREATE);
		BridgeHelper.getHamper().put(this, State.UPDATE);
	}

	@Override
	public SublineInterface createSubline()
	{
		return new Line(true, this.id);
	}

	@Override
	public void delete(SublineInterface subline)
	{
		BridgeHelper.getHamper().put(subline, State.DELETE);
		BridgeHelper.getHamper().put(this, State.UPDATE);
	}

	@Override
	@SuppressWarnings("unchecked")
	public ArrayList<SublineInterface> fetchSublines()
	{
		BasicDBObject predicate = new BasicDBObject();

		predicate.put("entry.parentLineId", this.id);
		predicate.put("entry.isSubline", true);
		
		String criteria = JSON.serialize(predicate);

		ArrayList<SublineInterface> subLines = Helper.query("Lines",criteria, WorkletContext.getInstance());
		
		return subLines;
	}

	@Override
	public Integer getNumber()
	{
		return number;
	}
	
	public void setNumber(Integer num)
	{
		this.number = num;
		BridgeHelper.getHamper().put(this, State.UPDATE);
	}

	@Override
	public void add(TransactionInterface transaction)
	{
		BridgeHelper.getHamper().put(transaction, State.CREATE);
		BridgeHelper.getHamper().put(this, State.UPDATE);
	}

	@Override
	public TransactionInterface createTransaction()
	{
		return new Transaction(id);
	}

	@Override
	public void delete(TransactionInterface transaction)
	{
		BridgeHelper.getHamper().put(transaction, State.DELETE);
		BridgeHelper.getHamper().put(this, State.UPDATE);
	}

	@Override
	public ArrayList<TransactionInterface> fetchTransactions()
	{
		BasicDBObject predicate = new BasicDBObject();

		predicate.put("entry.parentLineId", this.id);
		predicate.put("entry.isSubline", false);
		
		String criteria = JSON.serialize(predicate);

		@SuppressWarnings("unchecked")
		ArrayList<TransactionInterface> transactions = Helper.query("Transactions",criteria, WorkletContext.getInstance());
		
		return transactions;
	}

	@Override
	public Integer getSubNumber()
	{
		return number;
	}
	
	public void setSubNumber(Integer subNum)
	{
		this.number = subNum;
		BridgeHelper.getHamper().put(this, State.UPDATE);
	}
	
	public Boolean getIsSubline()
	{
		return isSubline;
	}

	public void setIsSubline(Boolean isSubline)
	{
		this.isSubline = isSubline;
	}

	public Integer getParentLineId()
	{
		return parentLineId;
	}

	public void setParentLineId(Integer parentLineId)
	{
		this.parentLineId = parentLineId;
	}

	public ArrayList<Integer> getTransactionIds()
	{
		return transactionIds;
	}

	public void setTransactionIds(ArrayList<Integer> transactionIds)
	{
		this.transactionIds = transactionIds;
	}

	public static long getSerialversionuid()
	{
		return serialVersionUID;
	}

	@Override
	public String getRepositoryName()
	{
		return repositoryName; 
	}
	public void setRepositoryName(String s){
		this.repositoryName = s;
	}

}